﻿
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace restful_sharp
{

    public class HttpResponseInfo
    {
        public long Duration { get; set; }
        public int StatusCode { get; set; }
        public string StatusText { get; set; }
        public string ContentType { get; set; }
        public long ContentLength { get; set; }
        public byte[] Body { get; set; }
        public Dictionary<string, string> Headers { get; set; }

        public HttpResponseInfo()
        {
            Headers = new Dictionary<string, string>();
        }
    }

    public class HTTP
    {
        private readonly HttpClient _httpClient;

        public HTTP()
        {
            var handler = new HttpClientHandler();

            // 忽略 SSL 证书错误  
            handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true;

            _httpClient = new HttpClient(handler);
        }

        public async Task<HttpResponseInfo> SendRequestAsync(
            string url,
            HttpMethod method,
            object body = null,
            string contentType = "application/json",
            Dictionary<string, string> headers = null
            )
        {
            HttpResponseMessage response = null;
            try
            {
                // 设置请求头  
                if (headers != null)
                {
                    foreach (var header in headers)
                    {
                        _httpClient.DefaultRequestHeaders.Add(header.Key, header.Value);
                    }
                }


                var requestMessage = new HttpRequestMessage(method, url);
                // 处理 GET 和 DELETE 请求  
                if (method == HttpMethod.Get || method == HttpMethod.Delete)
                {
                    //var formData = new List<string>();

                    //// 构建查询字符串  
                    //var queryString = new FormUrlEncodedContent(formData.Select(kvp => new KeyValuePair<string, string>(kvp.Key, kvp.Value.ToString()))).ReadAsStringAsync().Result;
                    //url = $"{url}?{queryString}";
                }
                else if (method == HttpMethod.Post || method == HttpMethod.Put)
                {
                    // 创建请求内容  
                    HttpContent httpContent = null;
                    if (body != null)
                    {
                        switch (contentType.ToLower())
                        {
                            case "application/json":
                                httpContent = new StringContent(Json.Serialize(body), Encoding.UTF8, contentType);
                                break;
                            case "application/x-www-form-urlencoded":
                                var formData = body as IDictionary<string, string>;
                                httpContent = new FormUrlEncodedContent(formData);
                                break;
                            case "multipart/form-data":
                                httpContent = CreateMultipartContent(body);
                                break;
                            //case "text/plain":
                            default:
                                httpContent = new StringContent(body.ToString(), Encoding.UTF8, contentType);
                                break;
                                //default:
                                //    throw new NotSupportedException($"Content type '{contentType}' is not supported.");
                        }
                    }
                    requestMessage.Content = httpContent;
                }

                var stopwatch = Stopwatch.StartNew();

                // 发送请求  
                response = await _httpClient.SendAsync(requestMessage);
                stopwatch.Stop();

                // 读取响应内容为 byte[]  
                byte[] responseContent = await response.Content.ReadAsByteArrayAsync();

                var responseInfo = new HttpResponseInfo
                {
                    Duration = stopwatch.ElapsedMilliseconds,
                    StatusCode = (int)response.StatusCode,
                    StatusText = response.ReasonPhrase,
                    ContentType = response.Content.Headers.ContentType?.ToString(),
                    ContentLength = response.Content.Headers.ContentLength ?? 0,
                    Body = responseContent
                };

                // 填充 Headers  
                foreach (var header in response.Headers)
                {
                    responseInfo.Headers[header.Key] = string.Join(", ", header.Value);
                }

                return responseInfo;
            }
            catch (Exception ex)
            {
                throw new Exception($"Error occurred while sending HTTP request: {ex.Message}", ex);
            }
            finally
            {
                response?.Dispose();
            }
        }
        private MultipartFormDataContent CreateMultipartContent(object body)
        {
            var multipartContent = new MultipartFormDataContent();

            // 假设 body 是一个字典，包含要发送的字段  
            var formData = body as IDictionary<string, object>;
            if (formData != null)
            {
                foreach (var item in formData)
                {
                    if (item.Value is FileInfo fileInfo)
                    {
                        // 如果值是 FileInfo，添加为文件内容  
                        var fileStream = fileInfo.OpenRead();
                        var fileContent = new StreamContent(fileStream);
                        fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                        multipartContent.Add(fileContent, item.Key, fileInfo.Name); // 使用文件名作为文件名  
                    }
                    else
                    {
                        // 否则，添加为普通表单字段  
                        multipartContent.Add(new StringContent(item.Value.ToString()), item.Key);
                    }
                }
            }

            return multipartContent;
        }
    }
}
